#pragma once
#include "detail.hpp"
#include "fields.hpp"
#include "abstract.hpp"

//抽象类的具体接口实现

namespace bitrpc{
    typedef std::pair<std::string, int>  Address;

    //Json格式信息处理
     class JsonMessage : public bitrpc::BaseMessage  {
        public:
            using ptr = std::shared_ptr<JsonMessage>;

            //实现序列化抽象类：JSON::Value -> string
            virtual std::string serialize() override
            {
                std::string body;
                bool ret = JSON::serialize(_body, body);
                if(ret == false)
                {
                    return std::string();
                }
                return body;
            } 
            //反序列化
            virtual bool unserialize(const std::string &msg) override 
            {
                return JSON::unserialize(msg, _body);
            }
        protected:
            Json::Value _body;
            
    };
////////////////////////////////////////////////////////////////////////////////////
//这两块还是设置一些公用的接口，比如设置状态码之类的

    //Json格式信息请求
    class JsonRequest : public JsonMessage
    {
        public:
            using ptr  = std::shared_ptr<JsonRequest>;
    };

    //Json格式信息响应
    //1.在响应中，大部分的响应都只有响应状态码
    //2.因此只需要判断响应状态码字段是否存在，类型是否正确即可
    //3.派生类继承基类的属性和方法
    //4.在feilds.hpp中设置了Json::Value对应[key, string::error]
    class JsonResponse : public JsonMessage
    {
        public:
            using ptr  = std::shared_ptr<JsonResponse>;

            //状态码检查
            virtual bool check() override{
                if(_body[KEY_RCODE].isNull() == true){
                    ELOG("响应没有相应状态码");
                    return false;
                }
                if(_body[KEY_RCODE.isIntegral() == false]){
                    ELOG("响应状态码类型错误");
                    return false;
                }
                return true;
            }

            //返回状态码
            virtual RCode RCode(){
                return (RCode)_body[KEY_RCODE].asInt();
            }

            //设置状态码
            virtual void setRCode(RCode rcode){
                _body[KEY_RCODE] = (int)rcode;
            }
    };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//以下 Request请求 基于功能特点，作为派生类基础了JsonMessage和BaseMessage基类，进行接口衍生

    //RPC请求，作为派生类基础了JsonMessage和BaseMessage基类
    //作为RPC功能，用于RPC功能丰富的接口实现
    class RpcRequest : public JsonRequest
    {
        public:
            using ptr = std::shared_ptr<RpcRequest>;

            //[KEY_METHOD] - method_name 方法名称
            // [KEY_PARAMS] - params Json::Value对象
            virtual bool check() override
            {
                if(_body[KEY_METHOD].isNull() == true || 
                    _body[KEY_METHOD].isString() == false){
                        ELOG("RPC请求中没有方法名称或方法名称类型错误");
                        return false;
                    }

                if(_body[KEY_PARAMS].isNull() == true ||
                    _body[KEY_PARAMS.isObject() == false]){
                        ELOG("RPC请求中没有参数信息或参数信息类型错误");
                        return false;
                    }
                    return true;
            }
            //设置/放回接口: 方法名称和对象
            std::string method(){
                return _body[KEY_METHOD].asString();
            }
            void setMethod(const std::string &method_name){
                _body[KEY_METHOD] = method_name;
            }
            Jsno::Value params(){
                return _body[KEY_PARAMS];
            }
            void setParams(const Json::Value &params)
            {
                _body[KEY_PARAMS] = params;
            }
     };

     //主题请求，作为派生类基础了JsonMessage和BaseMessage基类
     class TopicRequest : public JsonRequest{
        public:
            using ptr = std::shared_ptr<TopicRequest>;

            //检查:Topic主题名称、主题操作类型、主题发布请求
            virtual bool check() override
            {
                if(_body[KEY_TOPIC_KEY].isNull() == true || 
                    _body[KEY_TOPIC_KEY].isString() == false){
                        ELOG("主题请求中没有主题名称或主题名称类型错误");
                        return false;
                    }

                if(_body[KEY_OPTYPE].isNull() == true ||
                    _body[KEY_OPTYPE].isObject() == false){
                        ELOG("主题请求中没有操作类型或操作类型错误");
                        return false;
                    }

                if (_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH &&
                    (_body[KEY_TOPIC_MSG].isNull() == true ||
                    _body[KEY_TOPIC_MSG].isString() == false)) {
                    ELOG("主题消息发布请求中没有消息内容字段或消息内容类型错误！");
                    return false;
                    }
                    return true;
            }

            //主题名称:设置和返回
            std::string topicKey(){
                return _body[KEY_TOPIC_KEY].asString();
            }
            void setMethod(const std::string &key){
                _body[KEY_TOPIC_KEY] = key;
            }
            //主题类型: 设置和返回
            TopicOptype optype(){
                return (TopicOptype)_body[KEY_OPTYPE].asInt();
            }
            void setOptype(TopicOptype optype){
                _body[KEY_OPTYPE] = (int)optype;
            }
            //主题消息: 设置和返回
            std::string topicMsg(){
                return _body[KEY_TOPIC_KEY].asString();
            }   
            void setTopicMsg(const std::string &msg){
                _body[KEY_TOPIC_MSG] = msg;
            }
     };

     //服务请求，作为派生类基础了JsonMessage和BaseMessage基类
     class ServiceRequest : public JsonRequest{
        public:
        using ptr = std::shared_ptr<ServiceRequest>;

        //检查：服务方法名称、操作类型、主机地址信息
        virtual bool check() override {
            if (_body[KEY_METHOD].isNull() == true ||
                _body[KEY_METHOD].isString() == false) {
                ELOG("服务请求中没有方法名称或方法名称类型错误！");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true ||
                _body[KEY_OPTYPE].isIntegral() == false) {
                ELOG("服务请求中没有操作类型或操作类型的类型错误！");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                (_body[KEY_HOST].isNull() == true ||
                _body[KEY_HOST].isObject() == false ||
                _body[KEY_HOST][KEY_HOST_IP].isNull() == true ||
                _body[KEY_HOST][KEY_HOST_IP].isString() == false ||
                _body[KEY_HOST][KEY_HOST_PORT].isNull() == true ||
                _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false)) {
                ELOG("服务请求中主机地址信息错误！");
                return false;
            }
            return true;
     }
        //服务方法名称: 设置和返回
        std::string method(){
            return _body[KEY_METHOD].asString();
        }
        void setMethod(const std::string& name){
            _body[KEY_METHOD] = name;
        }
        //服务操作类型: 设置和返回
        ServiceOptype optype(){
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void setOptype(ServiceOptype optype){
            _body[KEY_OPTYPE] = (int)optype;
        }
        //服务主机信息: 设置和返回
        Address host(){
            Address addr;
            addr.first = _body[KEY_HOST][KET_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &host){
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _body[KEY_HOST] = value;
        }
        //【遇到的问题】:1.addr属于pair类型，刚开始addr.first = _body[KEY_HOST_IP]忘记他是一个数组 2.宏不能被调试比较麻烦
        //_body[KEY_HOST]找到外层Json::Value对象，内部还有Json::Value数组[KEY_HOST_IP]和[KEY_HOST_PORT]处理
    };

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//以下 Request请求 基于功能特点，作为派生类基础了JsonResponse 和BaseMessage基类，进行接口衍生


    //RPC响应，作为派生类基础了JsonResponse和BaseMessage基类
    class RpcResponse : public JsonResponse {
        public:
            using ptr = std::shared_ptr<RpcResponse>;

            //检查:响应状态码
            virtual bool check() override {
                if (_body[KEY_RCODE].isNull() == true ||
                    _body[KEY_RCODE].isIntegral() == false) {
                    ELOG("响应中没有响应状态码,或状态码类型错误！");
                    return false;
                }
                if (_body[KEY_RESULT].isNull() == true) {
                    ELOG("响应中没有Rpc调用结果,或结果类型错误！");
                    return false;
                }
                return true;
            }

            //RPC响应结果:请求和放回
            Json:: Value result(){
                return _body[KEY_RESULT];
            }
            void setResult(const Json::Value &result){
                _body[KEY_RESULT] = result;
            }
    };

    //Topic主题响应，作为派生类基础了JsonResponse和BaseMessage基类
    class TopicResponse : public JsonResponse{
        public:
            using ptr = std::shared_ptr<TopicResponse>;
    };
    //问题：在TopicResponse类中，没有过多处理？
    //回答:对于主题订阅、发布或取消订阅等操作，客户端通常只需要知道操作是否成功，
    //而不需要其他额外的信息。如果操作失败，状态码本身就能表明失败的原因。

    //Service响应，作为派生类基础了JsonResponse和BaseMessage基类
    class ServiceRespose : public JsonResponse{
        public:
            using ptr = std::shared_ptr<ServiceRequest>;
            //检查:响应状态码、操作类型、服务发现这块
            //问题:为什么这里要添加服务发现
                virtual bool check() override {
                if (_body[KEY_RCODE].isNull() == true ||
                    _body[KEY_RCODE].isIntegral() == false) {
                    ELOG("响应中没有响应状态码,或状态码类型错误！");
                    return false;
                }
                if (_body[KEY_OPTYPE].isNull() == true ||
                    _body[KEY_OPTYPE].isIntegral() == false) {
                    ELOG("响应中没有操作类型,或操作类型的类型错误！");
                    return false;
                }
                if (_body[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                   (_body[KEY_METHOD].isNull() == true ||
                    _body[KEY_METHOD].isString() == false ||
                    _body[KEY_HOST].isNull() == true ||
                    _body[KEY_HOST].isArray() == false)) {
                    ELOG("服务发现响应中响应信息字段错误！");
                    return false;
                }
                return true;
            }
            //服务操作类型: 设置和返回
            ServiceOptype optype() {
                return (ServiceOptype)_body[KEY_OPTYPE].asInt();
            }
            void setOptype(ServiceOptype optype) {
                _body[KEY_OPTYPE] = (int)optype;
            }
            //服务方法类型: 设置和返回
            std::string method() {
                return _body[KEY_METHOD].asString();
            }
            void setMethod(const std::string &method) {
                _body[KEY_METHOD] = method;
            }
            //服务主机地址信息: 设置和返回
            void setHost(std::vector<Address> addrs)
            {
                for(auto &addr : addrs){
                    Json::Value val;
                    val[KEY_HOST_IP] = addr.first;
                    val[KEY_HOST_PORT] = addr.second;
                    _body[KEY_HOST] = val;
                }
            }
            std::vector<Address> host(){
                std::vector<Address> addrs;
                int sz =_body[KEY_HOST].size();
                for(int i = 0; i < sz; i++){
                    Address addr;
                    addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
                    addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
                    addrs.push_back(addr);
                }
                return addrs;
            }
    };

    //消息对象工厂类:主要包含[RPC\TOPIC\SERVICE]对应的请求和响应
    class BaseMessageFactory{
        public:
         static BaseMessage::ptr create(MType mtype) {
        switch(mtype) {
            case MType::REQ_RPC: return std::make_shared<RpcRequest>();
            case MType::RSP_RPC: return std::make_shared<RpcResponse>();
            case MType::REQ_TOPIC: return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC: return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE: return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE: return std::make_shared<ServiceResponse>();
        }
        return BaseMessage::ptr();
    }
    //【问题】:在设计方面，针对不同的类型处理需要对应的函数返回值(一个函数不可能存在多个返回值)
    //解决办法:使用父类指针统一管理，后续想要具体使用可以通过dynamic_cast安全转化
    

    //泛型编程
    template<typename T, typename ...Args>
    static std::shared_ptr<T> create(Args&&... args) {
        return std::make_shared<T>(std::forward<Args>(args)...);
    }
    };
}